﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Collections;
using System.ComponentModel;

/// <summary>
/// Summary description for ENT
/// </summary>
public sealed class ENT
{

}

public class Customer : IComparable
{
    public int? CustomerId { get; set; }
    public string CustomerCode { get; set; }
    public string CustomerName { get; set; }
    public DateTime RegisterDate { get; set; }
    public DateTime UnregisterDate { get; set; }
    public string RegisteredBy { get; set; }
    public string UnregisteredBy { get; set; }
    public CustomerClientLoVCollection LOVs { get; set; }

    /// <summary>
    /// For empty init
    /// </summary>
    public Customer()
    {

    }

    /// <summary>
    /// For New Customers init.
    /// </summary>
    /// <param name="code"></param>
    /// <param name="name"></param>
    /// <param name="registeredby"></param>
    public Customer(string code, string name, string registeredby)
    {
        this.CustomerCode = code;
        this.CustomerName = name;
        this.RegisteredBy = registeredby;
        this.RegisterDate = DateTime.Now;
    }

    /// <summary>
    /// For Update,Delete Customers init.
    /// </summary>
    /// <param name="id"></param>
    /// <param name="newname"></param>
    /// <param name="op"></param>
    /// <param name="unregisteredby"></param>
    public Customer(int id, string newname, ENU.ENTOperation op, string unregisteredby = null)
    {
        try
        {
            this.CustomerId = id;
            
            switch (op)
            {
                case ENU.ENTOperation.Update:
                    if (newname == null)
                    {
                        throw new ArgumentNullException("newname must not be empty");
                    }
                    this.CustomerName = newname;
                    break;
                case ENU.ENTOperation.Delete:
                    if (unregisteredby == null)
                    {
                        throw new ArgumentNullException("unregisteredby must not be empty");
                    }
                    this.UnregisteredBy = unregisteredby;
                    this.UnregisterDate = DateTime.Now;
                    break;
                case ENU.ENTOperation.Insert:
                    throw new InvalidOperationException("Insert can not bue used here");
                default:
                    throw new InvalidOperationException("Invalid ENTOperation");
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    public int CompareTo(object obj)
    {
        //check to see if the type being passed is of the Customer type
        if (!(obj is Customer))
        {
            //since its not we need to throw an ArgumentException
            throw new ArgumentException("Object provided is of the wrong type");
        }
        //convert the object being passed to the type Customer
        Customer cs = (Customer)obj;
        //execute CompareTo and set its return value to our int variable
        int cmpl = this.CustomerCode.CompareTo(cs.CustomerCode);
        //check the value of the CompareTo method
        if (!(cmpl == 0))
        {
            //not equal to zero, meaning it isnt the right object
            return cmpl;
        }
        return this.CustomerCode.CompareTo(cs.CustomerCode);
    }

    /// <summary>
    /// Get single customer
    /// </summary>
    /// <param name="customerid">id of the customer</param>
    /// <returns>Customer</returns>
    public Customer GetCustomerById(int customerid)
    {
        Customer cs = new Customer();
        try
        {
            DataTable dt = DAL.GetCustomerById(customerid);
            cs.CustomerId = Int32.Parse(dt.Rows[0]["CustomerId"].ToString());
            cs.CustomerCode = dt.Rows[0]["CustomerCode"].ToString();
            cs.CustomerName = dt.Rows[0]["CustomerName"].ToString();
            if (dt.Rows[0]["RegisterDate"].ToString() != DBNull.Value.ToString())
            {
                cs.RegisterDate = DateTime.Parse(dt.Rows[0]["RegisterDate"].ToString());
            }
            cs.RegisteredBy = dt.Rows[0]["RegisteredBy"].ToString();
            if (dt.Rows[0]["UnregisterDate"].ToString() != DBNull.Value.ToString())
            {
                cs.UnregisterDate = DateTime.Parse(dt.Rows[0]["UnregisterDate"].ToString());
            }

            cs.UnregisteredBy = dt.Rows[0]["UnregisteredBy"].ToString();
            CustomerClientLoV lov = new CustomerClientLoV();
            cs.LOVs = lov.LoadAll((cs.CustomerId ?? 0), ENU.Entity.Customer, ENU.CCLovLoadOption.LoadAll, null, null);
        }
        catch (Exception ex)
        {
            throw ex;
        }

        return cs;
    }

    /// <summary>
    /// Gets Customer Collection, to get as Datatable, after call, see CustomerListTable in Collection.
    /// </summary>
    /// <param name="IsActive">Default: true, if true only active customers else all customers</param>
    /// <returns>CustomerCollection</returns>
    public CustomerCollection GetAllCustomers(bool IsActive = true)
    {
        try
        {
            DataTable dt = DAL.GetCustomerList(IsActive);
            CustomerCollection csc = new CustomerCollection();
            csc.CustomerListTable = dt;
            Customer cs = null;
            CustomerClientLoV lov = new CustomerClientLoV();
            foreach (DataRow dr in dt.Rows)
            {
                cs = new Customer();
                cs.CustomerId = Int32.Parse(dr["CustomerId"].ToString());
                cs.CustomerCode = dr["CustomerCode"].ToString();
                cs.CustomerName = dr["CustomerName"].ToString();
                if (dr["RegisterDate"].ToString() != DBNull.Value.ToString())
                {
                    cs.RegisterDate = DateTime.Parse(dr["RegisterDate"].ToString());
                }
                cs.RegisteredBy = dr["RegisteredBy"].ToString();
                if (dr["UnregisterDate"].ToString() != DBNull.Value.ToString())
                {
                    cs.UnregisterDate = DateTime.Parse(dr["UnregisterDate"].ToString());
                }
                cs.UnregisteredBy = dr["UnregisteredBy"].ToString();

                cs.LOVs = lov.LoadAll((cs.CustomerId ?? 0), ENU.Entity.Customer, ENU.CCLovLoadOption.LoadAll, null, null);
                csc.Add(cs);
            }

            return csc;
        }
        catch (Exception ex)
        {
            throw ex;
        }


    }

    /// <summary>
    /// Gets Customer Collection, to get as Datatable, after call, see CustomerListTable in Collection.
    /// </summary>
    /// <param name="TextToSearch"></param>
    /// <returns>CustomerCollection</returns>
    public CustomerCollection SearchCustomerByName(string TextToSearch)
    {
        try
        {
            DataTable dt = DAL.GetCustomerListByName(TextToSearch);
            CustomerCollection csc = new CustomerCollection();
            csc.CustomerListTable = dt;
            Customer cs = null;
            CustomerClientLoV lov = new CustomerClientLoV();
            foreach (DataRow dr in dt.Rows)
            {
                cs = new Customer();
                cs.CustomerId = Int32.Parse(dr["CustomerId"].ToString());
                cs.CustomerCode = dr["CustomerCode"].ToString();
                cs.CustomerName = dr["CustomerName"].ToString();
                if (dr["RegisterDate"].ToString() != DBNull.Value.ToString())
                {
                    cs.RegisterDate = DateTime.Parse(dr["RegisterDate"].ToString());
                }
                cs.RegisteredBy = dr["RegisteredBy"].ToString();
                if (dr["UnregisterDate"].ToString() != DBNull.Value.ToString())
                {
                    cs.UnregisterDate = DateTime.Parse(dr["UnregisterDate"].ToString());
                }
                cs.UnregisteredBy = dr["UnregisteredBy"].ToString();

                cs.LOVs = null;//lov.LoadAll((cs.CustomerId ?? 0), ENU.Entity.Customer, ENU.CCLovLoadOption.LoadAll, null, null);
                csc.Add(cs);
            }

            return csc;
        }
        catch (Exception ex)
        {
            throw ex;
        }


    }

    public ClientCollection GetAllClients(bool IsActive = false)
    {
        try
        {
            if (this.CustomerId == null)
            {
                throw new ArgumentNullException("CustomerId");
            }

            Client cl = new Client();
            return cl.GetAllClients((this.CustomerId ?? 0), IsActive);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    public bool Save(ref Exception exin)
    {
        try
        {
            if (!Validate(ref exin))
            {
                throw exin;
            }

            //For new Inserts
            if (this.CustomerId == null)
            {
                int RecordId;
                if (!DAL.InsertCustomer(this.CustomerCode, this.CustomerName, this.RegisteredBy, out RecordId))
                {
                    throw new OperationCanceledException("Customer Insert, Details logged to DB");
                }
                else
                {
                    this.CustomerId = RecordId;
                    if (this.LOVs != null)
                    {
                        if (!this.LOVs.Save())
                        {
                            throw new Exception("Unable to save LOVs for new record");
                        }
                    }
                }
                return true;
            }
            else //it is an update or a delete
            {
                if (!DAL.UpdateCustomer((this.CustomerId ?? 0), this.CustomerName, this.UnregisteredBy))
                {
                    throw new OperationCanceledException("Customer Update, Details logged to DB");
                }

                if (this.LOVs != null)
                {
                    if (!this.LOVs.Save())
                    {
                        throw new Exception("Unable to save LOVs for new record");
                    }
                }
                return true;
            }

        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public bool Validate(ref Exception exin)
    {
        try
        {
            //Check arguments:
            if (this.CustomerId == null && this.CustomerCode == null)
            {
                throw new ArgumentNullException("CustomerCode");
            }
            if (this.CustomerName == null)
            {
                throw new ArgumentNullException("CustomerName");
            }
            if (this.CustomerId == null && this.RegisteredBy == null)
            {
                throw new ArgumentNullException("RegisteredBy");
            }
            if (this.CustomerId != null && this.CustomerName==null && this.UnregisteredBy == null)
            {
                throw new ArgumentNullException("UnregisteredBy");
            }
            if (this.CustomerCode != null)
            {
                if (!DAL.CustomerCodeValidate(this.CustomerCode))
                {
                    throw new ArgumentException("CustomerCode not valid");
                }
            }
            exin = null;
            return true;
        }
        catch (Exception ex)
        {
            exin = ex;
            return false;
        }
    }
}

public class CustomerCollection : CollectionBase
{
    public DataTable CustomerListTable { get; set; }

    public Customer this[int idx]
    {
        get
        {
            return (Customer)this.InnerList[idx];
        }

    }

    public Customer this[string CustomerCode]
    {
        get
        {
            Customer found = null;
            foreach (Customer item in this.InnerList)
            {
                if (item.CustomerCode == CustomerCode)
                {
                    found = item;
                }
            }

            return found;
        }

    }

    public CustomerCollection()
    {

    }

    public void Add(Customer cs)
    {
        //add this item to the list
        this.InnerList.Add(cs);
    }

    public void Remove(Customer cs)
    {
        //check to see if the list contains this item, if it doesnt exit the procedure
        if (!this.Contains(cs)) return;
        //declare a counter variable
        int i;
        //loop through all the items in the list
        for (i = 0; i <= this.InnerList.Count; i++)
        {
            //create an instance of the IPAddress
            Customer item = (Customer)this.InnerList[i];
            //now check to see if its in the list
            if ((item.CompareTo(cs) == 0))
            {
                //if its in the list remove it
                this.RemoveAt(i);
                return;
            }
        }
    }

    public bool Contains(Customer cs)
    {
        //loop through all the items in the list
        foreach (Customer item in this.InnerList)
        {
            //check to see if its in the list returning 0 means its in the list
            if (item.CompareTo(cs) == 0)
            {
                //return true
                return true;
            }
        }
        //not in the list return false
        return false;
    }

    protected override void OnValidate(object value)
    {
        //first validate the object
        base.OnValidate(value);
        //if the object isnt of the correct type throw an ArgumentException
        if (!(value is Customer))
        {
            throw new ArgumentException("Collection only supports items of type Customer");
        }
    }

    public int IndexOf(Customer cs)
    {
        return this.InnerList.IndexOf(cs);
    }

    public Customer[] ToArray()
    {
        return (Customer[])this.InnerList.ToArray(typeof(Customer));
    }

    public List<Customer> ToList()
    {
        return this.ToArray().ToList<Customer>();
    }

}

public class Client : IComparable
{
    public Customer Customer { get; set; }
    public int? ClientId { get; set; }
    public string ClientCode { get; set; }
    public string ClientName { get; set; }
    public DateTime RegisterDate { get; set; }
    public DateTime UnregisterDate { get; set; }
    public string RegisteredBy { get; set; }
    public string UnregisteredBy { get; set; }
    public CustomerClientLoVCollection LOVs { get; set; }

    /// <summary>
    /// For empty init
    /// </summary>
    public Client()
    { }

    /// <summary>
    /// For New Clients init.
    /// </summary>
    /// <param name="code"></param>
    /// <param name="name"></param>
    /// <param name="registeredby"></param>
    public Client(string code, string name, string registeredby, int customerid)
    {
        Customer c = new Customer();
        this.Customer = c.GetCustomerById(customerid);
        this.ClientCode = code;
        this.ClientName = name;
        this.RegisteredBy = registeredby;
        this.RegisterDate = DateTime.Now;
    }

    /// <summary>
    /// For Update,Delete Clients init.
    /// </summary>
    /// <param name="id"></param>
    /// <param name="newname"></param>
    /// <param name="op"></param>
    /// <param name="unregisteredby"></param>
    public Client(int id, string name, int customerid, ENU.ENTOperation op, string unregisteredby = null)
    {
        try
        {
            Customer c = new Customer();
            this.Customer = c.GetCustomerById(customerid);
            this.ClientId = id;
            if (this.Customer == null)
            {
                throw new ArgumentNullException("Cant find customer for customerid=" + customerid.ToString());
            }
            switch (op)
            {
                case ENU.ENTOperation.Update:
                    if (name==null)
                    {
                        throw new ArgumentNullException("name must not be empty");
                    }
                    this.ClientName = name;
                    break;
                case ENU.ENTOperation.Delete:
                    if (unregisteredby == null)
                    {
                        throw new ArgumentNullException("unregisteredby must not be empty");
                    }
                    this.UnregisteredBy = unregisteredby;
                    this.UnregisterDate = DateTime.Now;
                    break;
                case ENU.ENTOperation.Insert:
                    throw new InvalidOperationException("Insert can not be used here");
                default:
                    throw new InvalidOperationException("Invalid ENTOperation");
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }

    }

    public int CompareTo(object obj)
    {
        //check to see if the type being passed is of the Client type
        if (!(obj is Client))
        {
            //since its not we need to throw an ArgumentException
            throw new ArgumentException("Object provided is of the wrong type");
        }
        //convert the object being passed to the type Customer
        Client cl = (Client)obj;
        //execute CompareTo and set its return value to our int variable
        int cmpl = this.ClientCode.CompareTo(cl.ClientCode);
        //check the value of the CompareTo method
        if (!(cmpl == 0))
        {
            //not equal to zero, meaning it isnt the right object
            return cmpl;
        }
        return this.ClientCode.CompareTo(cl.ClientCode);
    }

    /// <summary>
    /// Get single client
    /// </summary>
    /// <param name="customerid">id of the client</param>
    /// <returns>Client</returns>
    public Client GetClientById(int Clientid)
    {
        Client cl = new Client();
        try
        {
            DataTable dt = DAL.GetClientById(Clientid);
            cl.ClientId = Int32.Parse(dt.Rows[0]["ClientId"].ToString());
            cl.ClientCode = dt.Rows[0]["ClientCode"].ToString();
            cl.ClientName = dt.Rows[0]["ClientName"].ToString();

            Customer cs = new Customer();
            cl.Customer = cs.GetCustomerById(Int32.Parse(dt.Rows[0]["CustomerId"].ToString()));

            if (dt.Rows[0]["RegisterDate"].ToString() != DBNull.Value.ToString())
            {
                cl.RegisterDate = DateTime.Parse(dt.Rows[0]["RegisterDate"].ToString());
            }
            cl.RegisteredBy = dt.Rows[0]["RegisteredBy"].ToString();
            if (dt.Rows[0]["UnregisterDate"].ToString() != DBNull.Value.ToString())
            {
                cl.UnregisterDate = DateTime.Parse(dt.Rows[0]["UnregisterDate"].ToString());
            }

            cl.UnregisteredBy = dt.Rows[0]["UnregisteredBy"].ToString();
            CustomerClientLoV lov = new CustomerClientLoV();
            cl.LOVs = lov.LoadAll((cl.ClientId ?? 0), ENU.Entity.Client, ENU.CCLovLoadOption.LoadAll, null, null);
        }
        catch (Exception ex)
        {
            throw ex;
        }

        return cl;
    }

    /// <summary>
    /// Gets Client Collection, to get as Datatable, after call, see ClientListTable in Collection.
    /// </summary>
    /// <param name="CustomerId"></param>
    /// <param name="IsActive">Default: true, if true only active Clients else all Clients</param>
    /// <returns>ClientCollection</returns>
    public ClientCollection GetAllClients(int CustomerId, bool IsActive = true)
    {
        try
        {
            DataTable dt = DAL.GetClientList(CustomerId, IsActive);
            ClientCollection clc = new ClientCollection();
            clc.ClientListTable = dt;
            Client cl = null;

            Customer cs = new Customer();
            cs = cs.GetCustomerById(CustomerId);
            CustomerClientLoV lov = null;
            foreach (DataRow dr in dt.Rows)
            {
                cl = new Client();
                cl.ClientId = Int32.Parse(dr["ClientId"].ToString());
                cl.ClientCode = dr["ClientCode"].ToString();
                cl.ClientName = dr["ClientName"].ToString();
                cl.Customer = cs;
                if (dr["RegisterDate"].ToString() != DBNull.Value.ToString())
                {
                    cl.RegisterDate = DateTime.Parse(dr["RegisterDate"].ToString());
                }
                cl.RegisteredBy = dr["RegisteredBy"].ToString();
                if (dr["UnregisterDate"].ToString() != DBNull.Value.ToString())
                {
                    cl.UnregisterDate = DateTime.Parse(dr["UnregisterDate"].ToString());
                }
                cl.UnregisteredBy = dr["UnregisteredBy"].ToString();
                lov = new CustomerClientLoV();
                cl.LOVs = lov.LoadAll((cl.ClientId ?? 0), ENU.Entity.Client, ENU.CCLovLoadOption.LoadAll, null, null);
                clc.Add(cl);
            }

            return clc;
        }
        catch (Exception ex)
        {
            throw ex;
        }


    }

    /// <summary>
    ///  Gets Client Collection, to get as Datatable, after call, see ClientListTable in Collection.
    /// </summary>
    /// <param name="TextToSearch"></param>
    /// <returns>ClientCollection</returns>
    public ClientCollection SearchClientByName(string TextToSearch)
    {
        try
        {
            DataTable dt = DAL.GetClientListByName(TextToSearch);
            ClientCollection clc = new ClientCollection();
            clc.ClientListTable = dt;
            Client cl = null;

            Customer cs = new Customer();
            
            CustomerClientLoV lov = null;
            foreach (DataRow dr in dt.Rows)
            {
                cl = new Client();
                cl.ClientId = Int32.Parse(dr["ClientId"].ToString());
                cl.ClientCode = dr["ClientCode"].ToString();
                cl.ClientName = dr["ClientName"].ToString();
                cl.Customer = null;// cs.GetCustomerById(Int32.Parse(dr["CustomerId"].ToString()));//Could be removed or fixed id later due to record count. Cos no need for searching.
                if (dr["RegisterDate"].ToString() != DBNull.Value.ToString())
                {
                    cl.RegisterDate = DateTime.Parse(dr["RegisterDate"].ToString());
                }
                cl.RegisteredBy = dr["RegisteredBy"].ToString();
                if (dr["UnregisterDate"].ToString() != DBNull.Value.ToString())
                {
                    cl.UnregisterDate = DateTime.Parse(dr["UnregisterDate"].ToString());
                }
                cl.UnregisteredBy = dr["UnregisteredBy"].ToString();
                lov = new CustomerClientLoV();
                cl.LOVs = null;//lov.LoadAll((cl.ClientId ?? 0), ENU.Entity.Client, ENU.CCLovLoadOption.LoadAll, null, null);//Could be removed or fixed id later due to record count. Cos no need for searching.
                clc.Add(cl);
            }

            return clc;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    public bool Save(ref Exception exin)
    {
        try
        {
            if (!Validate(ref exin))
            {
                throw exin;
            }

            //For new Inserts
            if (this.ClientId == null)
            {
                int RecordId;
                if (!DAL.InsertClient(this.ClientCode, this.ClientName, (this.Customer.CustomerId ?? 0), this.RegisteredBy, out RecordId))
                {
                    throw new OperationCanceledException("Client Insert, Details logged to DB");
                }
                else
                {
                    this.ClientId = RecordId;
                    if (this.LOVs!=null)
                    {
                        if (!this.LOVs.Save())
                        {
                            throw new Exception("Unable to save LOVs for new record");
                        }
                    }
                }
                return true;
            }
            else //it is an update or a delete
            {
                if (!DAL.UpdateClient((this.ClientId ?? 0), this.ClientName, this.UnregisteredBy))
                {
                    throw new OperationCanceledException("Client Update, Details logged to DB");
                }
                else
                {
                    if (this.LOVs != null)
                    {
                        if (!this.LOVs.Save())
                        {
                            throw new Exception("Unable to save LOVs for new record");
                        }
                    }
                }
                return true;
            }

        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public bool Validate(ref Exception exin)
    {
        try
        {
            //Check arguments:
            if (this.ClientId == null && this.ClientCode == null)
            {
                throw new ArgumentNullException("ClientCode");
            }
            if (this.ClientName == null)
            {
                throw new ArgumentNullException("ClientName");
            }
            if (this.Customer == null)
            {
                throw new ArgumentNullException("Customer");
            }
            if (this.ClientId == null && this.RegisteredBy == null)
            {
                throw new ArgumentNullException("RegisteredBy");
            }
            if (this.ClientId != null && this.ClientName==null && this.UnregisteredBy == null)
            {
                throw new ArgumentNullException("UnregisteredBy");
            }
            if (this.ClientCode !=null)
            {
                if (!DAL.ClientCodeValidate(this.ClientCode))
                {
                    throw new ArgumentException("ClientCode not valid");
                }
            }

            exin = null;
            return true;
        }
        catch (Exception ex)
        {
            exin = ex;
            return false;
        }
    }    
}

public class ClientCollection : CollectionBase
{
    public DataTable ClientListTable { get; set; }

    public Client this[int idx]
    {
        get
        {
            return (Client)this.InnerList[idx];
        }

    }

    public Client this[string ClientCode]
    {
        get
        {
            Client found = null;
            foreach (Client item in this.InnerList)
            {
                if (item.ClientCode == ClientCode)
                {
                    found = item;
                }
            }

            return found;
        }

    }

    public ClientCollection()
    {

    }

    public void Add(Client cl)
    {
        //add this item to the list
        this.InnerList.Add(cl);
    }

    public void Remove(Client cl)
    {
        //check to see if the list contains this item, if it doesnt exit the procedure
        if (!this.Contains(cl)) return;
        //declare a counter variable
        int i;
        //loop through all the items in the list
        for (i = 0; i <= this.InnerList.Count; i++)
        {
            //create an instance of the IPAddress
            Client item = (Client)this.InnerList[i];
            //now check to see if its in the list
            if ((item.CompareTo(cl) == 0))
            {
                //if its in the list remove it
                this.RemoveAt(i);
                return;
            }
        }
    }

    public bool Contains(Client cl)
    {
        //loop through all the items in the list
        foreach (Client item in this.InnerList)
        {
            //check to see if its in the list returning 0 means its in the list
            if (item.CompareTo(cl) == 0)
            {
                //return true
                return true;
            }
        }
        //not in the list return false
        return false;
    }

    protected override void OnValidate(object value)
    {
        //first validate the object
        base.OnValidate(value);
        //if the object isnt of the correct type throw an ArgumentException
        if (!(value is Client))
        {
            throw new ArgumentException("Collection only supports items of type Client");
        }
    }

    public int IndexOf(Client cl)
    {
        return this.InnerList.IndexOf(cl);
    }

    public Client[] ToArray()
    {
        return (Client[])this.InnerList.ToArray(typeof(Client));
    }

    public List<Client> ToList()
    {
        return this.ToArray().ToList<Client>();
    }

}

public class CustomerClientLoV : IComparable
{
    public int RecId { get; set; }
    public int CustomerOrClientId { get; set; }
    public ENU.Entity CustomerOrClient { get; set; }
    public ENU.CCLoVRecordType RecordType { get; set; }
    public string RecordTypeString { get; set; }
    public ENU.CCLoVRecordName RecordName { get; set; }
    public string RecordNameString { get; set; }
    public string Description { get; set; }
    public string RecordValue { get; set; }
    public string LastSavedBy { get; set; }
    public DateTime LastSavedDate { get; set; }
    public ENU.RecStatus RecStatus { get; set; }

    public CustomerClientLoV()
    {

    }

    public CustomerClientLoV Init(int recid, int customerorclientid, ENU.Entity customerorclient, ENU.CCLoVRecordType lovrecordtype, ENU.CCLoVRecordName lovrecordname, string description, string value, string lastsavedby, DateTime lastsaveddate, ENU.RecStatus recstatus)
    {
        this.RecId = recid;
        this.CustomerOrClientId = customerorclientid;
        this.CustomerOrClient = customerorclient;
        this.RecordType = lovrecordtype;
        this.RecordTypeString = lovrecordtype.ToString();
        this.RecordName = lovrecordname;
        this.RecordNameString = lovrecordname.ToString();
        this.Description = description;
        this.RecordValue = value;
        this.RecStatus = recstatus;
        this.LastSavedBy = lastsavedby;
        this.LastSavedDate = lastsaveddate;
        return this;
    }

    public int CompareTo(object obj)
    {
        //check to see if the type being passed is of the CustomerClientLoV type
        if (!(obj is CustomerClientLoV))
        {
            //since its not we need to throw an ArgumentException
            throw new ArgumentException("Object provided is of the wrong type");
        }
        //convert the object being passed to the type CustomerClientLoV
        CustomerClientLoV lov = (CustomerClientLoV)obj;
        //execute CompareTo and set its return value to our int variable
        int cmpl = this.RecId.CompareTo(lov.RecId);
        //check the value of the CompareTo method
        if (!(cmpl == 0))
        {
            //not equal to zero, meaning it isnt the right object
            return cmpl;
        }
        return this.RecId.CompareTo(lov.RecId);
    }

    public CustomerClientLoVCollection LoadAll(int CustomerOrClientId, ENU.Entity CustomerOrClient, ENU.CCLovLoadOption LoadOption, ENU.CCLoVRecordType? RecordType, ENU.CCLoVRecordName? RecordName)
    {
        try
        {
            DataTable dt = null;
            switch (LoadOption)
            {
                case ENU.CCLovLoadOption.LoadAll:
                    dt = DAL.GetLOVList(CustomerOrClient, CustomerOrClientId, null, null);
                    break;
                case ENU.CCLovLoadOption.LoadOneRecordType:
                    dt = DAL.GetLOVList(CustomerOrClient, CustomerOrClientId, RecordType.ToString(), null);
                    break;
                case ENU.CCLovLoadOption.LoadOneRecordNameUnderARecordType:
                    dt = DAL.GetLOVList(CustomerOrClient, CustomerOrClientId, RecordType.ToString(), RecordName.ToString());
                    break;
                default:
                    break;
            }
            CustomerClientLoVCollection lovc = new CustomerClientLoVCollection();
            CustomerClientLoV lov = null;
            foreach (DataRow dr in dt.Rows)
            {
                int recid = Int32.Parse(dr["RecId"].ToString());
                int customerorclientid = Int32.Parse(dr["CustomerOrClientId"].ToString());
                ENU.Entity customerorclient = ENU.EntityParse(dr["CustomerOrClient"].ToString());
                ENU.CCLoVRecordType lovrecordtype = ENU.RecordTypeParse(dr["RecordType"].ToString());
                ENU.CCLoVRecordName lovrecordname = ENU.RecordNameParse(dr["RecordName"].ToString());
                string description = dr["Description"].ToString();
                string recordvalue = dr["RecordValue"].ToString();
                string lastsavedby = dr["LastSavedBy"].ToString();
                DateTime lastsaveddate = DateTime.Parse(dr["LastSavedDate"].ToString());
                lov = new CustomerClientLoV();
                lov = lov.Init(recid, customerorclientid, customerorclient, lovrecordtype, lovrecordname, description, recordvalue, lastsavedby, lastsaveddate, ENU.RecStatus.NoChange);
                lovc.Add(lov);
            }
            lovc.Sort();
            return lovc;
        }
        catch (Exception ex)
        {
            throw ex;
        }

    }

    public bool Save()
    {
        try
        {
            switch (this.RecStatus)
            {
                case ENU.RecStatus.NoChange:
                    return true;
                case ENU.RecStatus.Added:
                    int RecordId;
                    return DAL.InsertLOV(this.CustomerOrClientId, this.CustomerOrClient, this.RecordType, this.RecordName, this.Description, this.RecordValue, this.LastSavedBy, out RecordId);
                case ENU.RecStatus.Modified:
                    return DAL.UpdateLOV(this.RecId, this.Description, this.RecordValue, this.LastSavedBy);
                case ENU.RecStatus.Deleted:
                    return DAL.DeleteLOV(this.RecId);
                default:
                    return false;
            }
        }
        catch (Exception ex)
        {
            ERR.Handler(ex, "LOVSave","RecId: " + this.RecId.ToString());
            return false;
        }
    }
}

public class CustomerClientLoVCollection : CollectionBase
{
    public DataTable CustomerClientLoVListTable { get; set; }

    public CustomerClientLoV this[int idx]
    {
        get
        {
            return (CustomerClientLoV)this.InnerList[idx];
        }

    }

    public CustomerClientLoVCollection()
    {

    }

    public void Add(CustomerClientLoV lov)
    {
        //add this item to the list
        this.InnerList.Add(lov);
    }

    public void Remove(CustomerClientLoV lov)
    {
        //check to see if the list contains this item, if it doesnt exit the procedure
        if (!this.Contains(lov)) return;
        //declare a counter variable
        int i;
        //loop through all the items in the list
        for (i = 0; i <= this.InnerList.Count; i++)
        {
            //create an instance of the IPAddress
            CustomerClientLoV item = (CustomerClientLoV)this.InnerList[i];
            //now check to see if its in the list
            if ((item.CompareTo(lov) == 0))
            {
                //if its in the list remove it
                this.RemoveAt(i);
                return;
            }
        }
    }

    public bool Contains(CustomerClientLoV lov)
    {
        //loop through all the items in the list
        foreach (CustomerClientLoV item in this.InnerList)
        {
            //check to see if its in the list returning 0 means its in the list
            if (item.CompareTo(lov) == 0)
            {
                //return true
                return true;
            }
        }
        //not in the list return false
        return false;
    }

    protected override void OnValidate(object value)
    {
        //first validate the object
        base.OnValidate(value);
        //if the object isnt of the correct type throw an ArgumentException
        if (!(value is CustomerClientLoV))
        {
            throw new ArgumentException("Collection only supports items of type CustomerClientLoV");
        }
    }

    public int IndexOf(CustomerClientLoV lov)
    {
        return this.InnerList.IndexOf(lov);
    }

    public CustomerClientLoV[] ToArray()
    {
        return (CustomerClientLoV[])this.InnerList.ToArray(typeof(CustomerClientLoV));
    }

    public List<CustomerClientLoV> ToList()
    {
        return this.ToArray().ToList<CustomerClientLoV>();
    }

    public void Sort()
    {
        this.InnerList.Sort(new CustomerClientLoVCollectionSorter());
    }

    public bool Save()
    {
        int failcount = 0;
        try
        {
            foreach (CustomerClientLoV lov in this)
            {
                if (!lov.Save())
                {
                    failcount++;
                }
            }

            if (failcount>0)
            {
                throw new Exception("Failed to persist LOV changes, see DB for details");
            }
            else
            {
                return true;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
    }
}

public class CustomerClientLoVCollectionSorter : IComparer
{
    public int Compare(object x, object y)
    {
        int iPrimaryComparison = ((CustomerClientLoV)x).RecordType.CompareTo(((CustomerClientLoV)y).RecordType);
        if (iPrimaryComparison == 0)
        {
            return ((CustomerClientLoV)x).RecordName.CompareTo(((CustomerClientLoV)y).RecordName);
        }
        else
            return iPrimaryComparison;
    }
}

public class KUser
{
    public int UserId { get; set; }
    public string LoginName { get; set; }
    public string UserFullName { get; set; }
    public string UserEmail { get; set; }
    public KUserRole Role { get; set; }
    
    public KUser()
    {

    }

    public bool Login(string loginname, string loginpass)
    {
        try
        {
            DataTable dt = DAL.GetUser(loginname, loginpass);
            if (dt.Rows.Count == 0)
            {
                return false;
            }
            else
            {
                this.LoginName = loginname;
                this.UserId = Int32.Parse(dt.Rows[0]["UserId"].ToString());
                this.UserFullName = dt.Rows[0]["UserFullName"].ToString();
                this.UserEmail = dt.Rows[0]["UserEmail"].ToString();
                KUserRole ur = new KUserRole();
                this.Role = ur.GetRole(this.UserId);
                return true;
            }
        }
        catch (ERR.UIException ex)
        {
            throw ex;
        }
    }
    public bool AllowedToSeePage(string PageFilePath)
    {
        try
        {
            if (this.UserId==null)
            {
                throw new ArgumentNullException("UserId can not be null, init user first");
            }
            if (this.Role==null)
            {
                throw new ArgumentNullException("User Role can not be null, init user and Role first");
            }
            if (this.Role.PermissionList == null)
            {
                throw new ArgumentNullException("User Role PermissionList can not be null, init user, Role and Permissions first");
            }
            if (this.Role.PermissionList.AllowedPageList.Contains(PageFilePath.ToLower()))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        catch (Exception ex)
        {
            ERR.Handler(ex, "KPage");
            throw ex;
        }
    }
}

public class KUserRole
{
    public int RoleId { get; set; }
    public string RoleName { get; set; }
    public KPermissions PermissionList { get; set; }
    public KUserRole GetRole(int UserId)
    {
        DataTable dt = DAL.GetUserRole(UserId);
        this.RoleId = Int32.Parse(dt.Rows[0]["RoleId"].ToString());
        this.RoleName = dt.Rows[0]["RoleName"].ToString();
        PermissionList = new KPermissions(this.RoleId);

        return this;
    }
}

public class KPermissions
{
    public List<string> AllowedPageList { get; set; }
    public KPermissions(int RoleId)
    {
        
        DataTable dt = DAL.GetRolePermission(RoleId);
        AllowedPageList = new List<string>();
        foreach (DataRow dr in dt.Rows)
        {
            AllowedPageList.Add(dr["PageFilePath"].ToString().ToLower());
        }        
    }
}